package com.leo.app;

import com.leo.app.handle.OnStart;
import com.leo.app.handle.OnStop;
import com.leo.app.handle.OnUpdate;
import javafx.animation.AnimationTimer;

/**
 * @ClassName Engine
 * @Description 引擎
 * @Author wangss
 * @date 2020.12.07 21:39
 * @Version 1.0
 */
public class Engine {

    private final Timer timer;

    /**
     * 当前帧
     */
    private double nowNanos;
    /**
     * 上一帧
     */
    private double lastNanos;
    /**
     * 相减帧
     */
    private double deltaNanos;

    /**
     * nanos per frame
     */
    private double npf;

    /**
     * Frames Per Second
     */
    private double fps;

    protected OnStart onStart;
    protected OnUpdate onUpdate;
    protected OnStop onStop;

    public Engine() {
        this(60);
    }

    public Engine(double fps) {
        timer = new Timer();
        this.setFps(fps);
    }


    public double getFps() {
        return fps;
    }

    public void setFps(double fps) {
        this.fps = fps;
        // 转换（纳秒）
        this.npf = 1E9 / fps;
    }

    public double getNowNanos() {
        return nowNanos;
    }

    public double getNowMillis() {
        return nowNanos * 1E-6;
    }

    public double getNowSecs() {
        return nowNanos * 1E-9;
    }

    public double getLastNanos() {
        return lastNanos;
    }

    public double getLastMillis() {
        return nowNanos * 1E-6;
    }

    public double getLastSecs() {
        return nowNanos * 1E-9;
    }

    public double getDeltaNanos() {
        return deltaNanos;
    }

    public double getNpf() {
        return npf;
    }

    protected void start() {
        timer.start();
    }

    protected void stop() {
        timer.stop();
    }

    private class Timer extends AnimationTimer {
        @Override
        public void start() {
            this.reset();
            super.start();
            if (null != onStart) {
                onStart.handle();
            }
        }

        /**
         * start()执行以后调用handle方法
         * @param now
         */
        @Override
        public void handle(long now) {
            nowNanos = now;
            if (lastNanos > 0) {
                deltaNanos += nowNanos - lastNanos;
            }
            lastNanos = nowNanos;

            if (deltaNanos >= npf) {
                if (onUpdate != null) {
                    onUpdate.handle(deltaNanos);
                }

                deltaNanos -= npf;
            }
        }

        @Override
        public void stop() {
            if (null != onStop) {
                onStop.handle();
            }
            super.stop();
            this.reset();
        }

        public void reset() {
            nowNanos = 0;
            lastNanos = 0;
            deltaNanos = 0;
        }
    }
}
